home *** CD-ROM | disk | FTP | other *** search
- #include "pop.h"
-
-
- /* Stuff for "From " Header */
- /* Courtesy Michael B. Smith */
-
-
- struct mytm {
- int year;
- int month;
- int day;
- int dow;
- int hour;
- int min;
- int sec;
- };
-
- /* DaysInMonth */
- static const int dim [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
- static const char *months [] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
- static const char *days [] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
-
- static void DateStampToMyTm (struct DateStamp *date, struct mytm *da)
- {
- int days, years, leap = 0, month = 0;
-
- days = date->ds_Days + 731; /* 1976 */
- years = days / (365*3+366); /* #quad yrs */
- days -= years * (365*3+366);
- years = 1976 + 4 * years;
-
- if (days <= 365)
- {
- leap = 1;
- }
- else
- {
- days -= 366;
- ++years;
- years += days / 365;
- days %= 365;
- }
-
- month = 0;
- while (1)
- {
- if (month == 1)
- {
- if (days < (28 + leap)) break;
- days -= 28 + leap;
- }
- else
- {
- if (days < dim [month]) break;
- days -= dim [month];
- }
- ++month;
- }
-
- da->hour = date->ds_Minute / 60;
- da->min = date->ds_Minute % 60;
- da->sec = date->ds_Tick / 50;
-
- da->day = days + 1;
- da->month = month + 1;
- da->dow = date->ds_Days % 7; /* 0 = sunday */
- da->year = years;
-
- return;
- }
-
- char * datestr (char *buf)
- {
- /*
- ** datestr
- **
- ** Build ARPA date-time as specified in RFC-822:
- **
- ** Wed, 13 Oct 93 18:52:04 EST
- ** 123456789012345678901234567890
- **
- ** buf must be 24 characters, plus space for TimeZone and NUL.
- **
- ** As TimeZone may be "(+23:30)" or similar, 33 chars should
- ** do it.
- */
- struct mytm da;
- struct DateStamp ds;
-
- DateStampToMyTm (DateStamp (&ds), &da);
-
- DoFmt (buf, "%s, %ld %s %ld %02ld:%02ld:%02ld",
- days [da.dow], da.day,
- months [da.month - 1], da.year % 100,
- da.hour, da.min, da.sec);
-
- return buf;
- }
-
- char * time_stamp (char *buf)
- {
- /*
- ** time_stamp
- **
- ** Put a time/date stamp into buf (for logging)
- **
- ** 13 Nov 93 13:14:45
- */
- struct DateStamp ds;
- struct mytm da;
-
- DateStampToMyTm (DateStamp (&ds), &da);
-
- DoFmt (buf, "%ld %s %ld %02ld:%02ld:%02ld",
- da.day,
- months [da.month - 1], da.year % 100,
- da.hour, da.min, da.sec);
-
- return buf;
- }
-
- /* End stuff for "From " header */
-
-
- #define ASYNCBUFSIZE 8192
-
- BOOL needfrom ( char * , struct AsyncFile *);
-
- /* Variables global to this file */
-
- struct Library *SockBase ;
- int havemail;
-
- /* Functions */
-
- int dopop(void)
- {
- int s;
- int count=1;
- int okay=1;
- struct hostent *hp;
- struct sockaddr_in sa;
-
- /*DoFmt(title,"Connecting to %s",pophost);
- settitle(title);*/
-
- if((SockBase = OpenLibrary( SOCKLIBNAME, SOCKLIBVERSION )) == NULL)
- {
- doreq("Error opening "SOCKLIBNAME"\n",bum);
- return(1);
- }
- #ifdef AMITCP
- SetErrnoPtr(&errno, sizeof errno);
- #else
- setup_sockets( MAXSOCKS, &errno );
- #endif
-
- if((hp=gethostbyname(pophost))==NULL)
- {
- #ifndef AMITCP
- cleanup_sockets();
- #endif
- CloseLibrary( SockBase ) ;
- doreq("Connection Refused.",bum);
- return(1);
- }
-
- bzero(&sa, sizeof(sa));
- bcopy(hp->h_addr, (char *)&sa.sin_addr, hp->h_length);
- sa.sin_family = hp->h_addrtype;
- sa.sin_port = htons((u_short)port);
- if ((s=socket(hp->h_addrtype,SOCK_STREAM,0)) < 0)
- {
- #ifndef AMITCP
- cleanup_sockets();
- #endif
- CloseLibrary( SockBase ) ;
- doreq("Something bad\nhas happened.",bum);
- return(1);
- }
-
- if (connect(s,(struct sockaddr *) &sa,sizeof(sa))< 0)
- {
- doreq("No POP3 daemon\nrunning on this\nmachine or port.",bum);
- s_close(s);
- #ifndef AMITCP
- cleanup_sockets();
- #endif
- CloseLibrary( SockBase ) ;
- return(1);
- }
-
- /* Put actual code here */
-
- /* We need to loop on this recv, because the initial greeting may not fit in one BUFSIZE.
- We loop until we get a "\n" */
-
- settitle("Got Connection");
-
- recv(s,buf,BUFSIZE-1,0);
- while (!(strstr(buf,"\n")))
- {
- recv(s,buf,BUFSIZE-1,0);
- }
-
-
- if (senduser(s))
- {
- #ifndef AMITCP
- cleanup_sockets();
- #endif
- CloseLibrary( SockBase ) ;
- return(1);
- }
-
- havemail=sendstat(s);
-
- while ((okay) && ((havemail > count) || (havemail == count)))
- {
- DoFmt(title,"Retrieving %lu of %lu",count,havemail);
- settitle(title);
-
- okay=retrieve(s,count);
-
- if (delmail && okay)
- {
- DoFmt(title,"Deleting %lu",count);
- settitle(title);
-
- okay=delmessage(s,count);
- }
- ++count;
- }
-
- if(sendquit(s))
- {
- #ifndef AMITCP
- cleanup_sockets();
- #endif
- CloseLibrary( SockBase ) ;
- return(1);
- }
-
- /*if (Project0Wnd)
- {
- SetWindowTitles(Project0Wnd,Project0Wdt, (UBYTE *) ~0);
- }*/
-
- if (havemail && notify) /* removed sendstat() after Nofify */
- {
- doreq("You have new mail.","Cool");
- }
-
- /* End actual code */
-
- s_close(s);
- #ifndef AMITCP
- cleanup_sockets();
- #endif
- CloseLibrary( SockBase ) ;
- return(0);
- }
-
- int senduser(int s)
- {
- int t;
-
- settitle("Sending Username");
-
- DoFmt(buf,"USER %s\r\n",username);
-
- if ( !trans(s,buf) ) return(1);
-
- t=sscanf(buf,"%s",temp);
- if ( valcheck(t,temp) ) return(1);
-
- /* Password */
-
- if (password[1])
- {
- settitle("Sending Password");
-
- DoFmt(buf,"PASS %s\r\n",password);
-
- if ( !trans(s,buf) ) return(1);
-
- t=sscanf(buf,"%s",temp);
-
- if ( valcheck(t,temp) ) return(1);
- }
-
- return(0);
- }
-
- int sendquit(int s)
- {
- int t;
-
- settitle("Sending QUIT");
-
- DoFmt(buf,"QUIT\r\n");
-
- if ( !trans(s,buf) ) return(1);
-
- t=sscanf(buf,"%s",temp);
-
- if ( valcheck(t,temp) ) return(1);
-
- settitle("Quit Acknowledged");
-
- return(0);
- }
-
- int sendstat( int s )
- {
- int t;
- int count=0;
-
- DoFmt(buf,"STAT\r\n");
-
- if ( !trans(s,buf) ) return(0);
-
- t=sscanf(buf,"%s %lu",temp,&count);
-
- if ( valcheck(t,temp) ) return(0);
-
- return(count);
- }
-
- /* function retrieve does the work of retrieving a message, removing
- the byte stuffing and writing it to the mailfile.
- Rewritten by David Duggan, Sandia National Labs */
-
- int retrieve(int s, int count)
- {
- int foo; /* temp integer for numb bytes read */
- int state; /* flag saying what state we are in */
- int x1; /* index for tmpbuf */
-
- char *tmpbuf; /* ptr to place to put unstuffed msg */
- char *buf3; /* ptr to front of mail message */
- char *buf4; /* ptr to char being examined in mail message */
-
- struct AsyncFile *ofp;
-
- if ( ! (tmpbuf = AllocVec(BUFSIZE,MEMF_CLEAR)))
- {
- doreq("Not enough memory for buffer.",bum);
- return(0);
- }
-
- if (( count == 1 ) && ( !appfile ))
- {
- ofp = OpenAsync(mailbox, MODE_WRITE,ASYNCBUFSIZE);
- }
- else
- {
- ofp = OpenAsync(mailbox, MODE_APPEND,ASYNCBUFSIZE);
- }
-
- if ( ofp == NULL )
- {
- doreq("Unable to lock Mailbox.\nCheck path and filename.",bum);
- FreeVec(tmpbuf);
- return(0);
- }
-
- DoFmt(buf,"RETR %lu\r\n",count);
-
- if ( !trans(s,buf) ) /* send data, get answer */
- {
- CloseAsync(ofp);
- FreeVec(tmpbuf);
- return(0);
- }
-
- if ( valcheck(1,buf) ) /* check for good response */
- {
- CloseAsync(ofp);
- FreeVec(tmpbuf);
- return(0);
- }
-
- /* Here we have a good first line for this multi-line response.
- Now we should process the rest of the buffer */
-
- buf3 = strstr(buf,"\r\n");
- if (buf3 != NULL) buf3 += 2;/* move ptr past first line */
- needfrom(buf3,ofp); /* add "from" if needed */
- buf4 = buf3 = strip(buf3); /* remove CRs */
-
- state = 0; /* start clean every time */
- while ( state < 3 )
- {
- x1 = 0; /* reset index */
- while ( *buf4 ) /* until we hit the end of buffer */
- {
- switch (state)
- {
- case 0:
- if ( *buf4 == '\n' )
- {
- state++; /* go to next state */
- }
- tmpbuf[x1++] = *buf4;/* move character */
- break;
-
- case 1:
- if ( *buf4 == '.' )
- {
- state++; /* next state, deleting period */
- }
- else
- { /* reset state if not "\n" */
- if (*buf4 != '\n')
- {
- state = 0;
- }
- tmpbuf[x1++] = *buf4;/* move character */
- }
- break;
-
- case 2:
- if ( *buf4 == '\n' )
- {
- state++; /* go to final state */
- }
- else
- {
- state = 0; /* reset the state */
- }
- tmpbuf[x1++] = *buf4;
- break;
- } /* switch */
- buf4++; /* move to next byte */
- }
-
- tmpbuf[x1] = '\0'; /* terminate it */
-
- if ( state < 3 ) /* we need more in the buffer */
- {
- if ( WriteAsync(ofp,tmpbuf,strlen(tmpbuf) ) == -1)
- {
- doreq("Error writing to mailbox.",bum);
- CloseAsync(ofp);
- FreeVec(tmpbuf);
- return(0); /* return error */
- }
-
- /* get next buffer full */
- foo = recv(s,buf,(BUFSIZE - 1),0);
-
- if ( foo > 0 )
- {
- buf[foo] = '\0'; /* terminate it for grins */
- buf4 = buf3 = strip(buf);/* remove CRs */
- }
- else
- { /* should never happen! */
- doreq("Internal Error.",bum);
- state = 4;/* should never happen */
- }
- } /* if (state < 3) */
- } /* while (state < 3) */
-
- /* write out last buffer, leaving off last ".\n" */
- if ( WriteAsync(ofp,tmpbuf,strlen(tmpbuf)) == -1 )
- {
- doreq("Error writing to Mailbox.",bum);
- CloseAsync(ofp);
- FreeVec(tmpbuf);
- return(0); /* return error */
- }
-
- CloseAsync(ofp);
- FreeVec(tmpbuf);
- return(1);
-
- } /* end of retrieve */
-
- int delmessage( int s, int count )
- {
- DoFmt(buf,"DELE %lu\r\n",count);
- trans(s,buf);
-
- if ( valcheck(1,buf) ) return(0);
-
- return(1);
- }
-
- int valcheck(int t, char *localtemp)
- {
- if (t == 0)
- {
- doreq("Got a bogus return string.",bum);
- return(1);
- }
-
- if ( !strstr(localtemp,"+OK") )
- {
- doreq("Didn't get +OK",bum);
-
- if (localtemp[0] != '\0')
- {
- doreq(localtemp,bum);
- }
- return(1);
- }
- return(0);
- }
-
- int trans( int s, char *mybuf )
- {
- int foo;
-
- send(s,mybuf,strlen(mybuf),0);
-
- bzero(buf,BUFSIZE);
- foo=recv(s,buf,BUFSIZE-1,0);
- if ( foo < 1 )
- {
- return(0);
- }
-
- buf[foo]='\0';
-
- return (1);
- }
-
- void settitle( char *newtitle )
- {
- if (winop)
- {
- SetWindowTitles(Project0Wnd,newtitle, (UBYTE *) ~0);
- }
- }
-
- /* Scott, this is a slight modification of your strip. It has the exact same
- functionality as yours, except it uses dynamic memory instead of the stack
- for the temporary buffer. If you want to leave your routine here,
- everything should work just the same. David */
-
- /* function strip will strip out all the carraige returns
- from the buffer and return the original pointer */
-
- char * strip( char *mybuf )
- {
- char tmpbuf[BUFSIZE];
- ULONG x1, x2, len;
-
- len = strlen(mybuf);
-
- /* strip out the CRs */
- for (x1 = x2 = 0 ; x1 < len; x1++)
- {
- tmpbuf[x2] = mybuf[x1];
- if ( tmpbuf[x2] != '\r' ) x2++;
- }
-
- tmpbuf[x2] = '\0'; /* terminate it */
- strcpy(mybuf,tmpbuf); /* copy back the string */
-
- return(mybuf); /* return their buf ptr */
-
- } /* end of strip */
-
- int lastblock (char *segment)
- {
- char *found;
- int len = strlen(segment);
-
- if ( (found=strstr(segment,"\r\n.\r\n")))
- {
- /*buf[found-segment]='\n';*/
- buf[found-segment]='\0'; /* used to be found-segment+2 */
- return(0);
- }
-
- if ( (len==2) && (found=strstr(segment,"\r\n")) )
- {
- buf[found-segment]='\0'; /* Added recently */
- return(0);
- }
-
- if ( len==1 ) /* Kludge of the century */
- {
- return(0);
- }
-
- if ( (len <= 4) && (found=strstr(segment,".\r\n")) )
- {
- /*buf[found-segment]='\n';*/
- buf[found-segment]='\0';
- return(0);
- }
-
- return(1);
- }
-
- BOOL needfrom(char *mybuf,struct AsyncFile *ofp)
- {
- if ( !strstr(mybuf,"From ") )
- {
- char *newtemp;
-
- if (newtemp=AllocVec(BIGSTRING,MEMF_CLEAR))
- {
- int tempsize=0;
-
- DoFmt(newtemp,"From %s@%s ", username,pophost);
- tempsize=strlen(newtemp);
- DoFmt((newtemp+tempsize),"%s\n",datestr((newtemp+tempsize)));
- WriteAsync(ofp,newtemp,strlen(newtemp));
- FreeVec(newtemp);
- }
-
- return(TRUE);
- }
- return(FALSE);
- }
-